From e927a5b2c7d0be1467f11b37353568862b4e95ec Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sat, 12 Nov 2011 03:39:48 +0100 Subject: [PATCH] treeview: Redo row tracking Track the RBNode/RBTree instead of keeping a TreeRowReference. This is a whole lot faster and less error-prone. Also, notify the accessible of removal of rows before actually removing them, so we have a chance to clean up. --- gtk/a11y/gtktreeviewaccessible.c | 82 +++++++++++++++++++++++++++++--- gtk/a11y/gtktreeviewaccessible.h | 6 +++ gtk/gtktreeview.c | 4 ++ 3 files changed, 86 insertions(+), 6 deletions(-) diff --git a/gtk/a11y/gtktreeviewaccessible.c b/gtk/a11y/gtktreeviewaccessible.c index 92505ccd76..d0798c3f20 100644 --- a/gtk/a11y/gtktreeviewaccessible.c +++ b/gtk/a11y/gtktreeviewaccessible.c @@ -25,6 +25,7 @@ #endif #include "gtktreeprivate.h" +#include "gtkwidgetprivate.h" #include "gtktreeviewaccessible.h" #include "gtkrenderercellaccessible.h" @@ -38,7 +39,8 @@ typedef struct _GtkTreeViewAccessibleCellInfo GtkTreeViewAccessibleCellInfo; struct _GtkTreeViewAccessibleCellInfo { GtkCellAccessible *cell; - GtkTreeRowReference *cell_row_ref; + GtkRBTree *tree; + GtkRBNode *node; GtkTreeViewColumn *cell_col_ref; GtkTreeViewAccessible *view; }; @@ -228,16 +230,15 @@ cell_info_free (GtkTreeViewAccessibleCellInfo *cell_info) _gtk_cell_accessible_add_state (cell_info->cell, ATK_STATE_DEFUNCT, FALSE); } - /* g_object_unref (cell_info->cell); */ - if (cell_info->cell_row_ref) - gtk_tree_row_reference_free (cell_info->cell_row_ref); g_free (cell_info); } static GtkTreePath * cell_info_get_path (GtkTreeViewAccessibleCellInfo *cell_info) { - return gtk_tree_row_reference_get_path (cell_info->cell_row_ref); + return _gtk_tree_view_find_path (NULL, + cell_info->tree, + cell_info->node); } static void @@ -3079,7 +3080,16 @@ cell_info_new (GtkTreeViewAccessible *accessible, GtkTreeViewAccessibleCellInfo *cell_info; cell_info = g_new (GtkTreeViewAccessibleCellInfo, 1); - cell_info->cell_row_ref = gtk_tree_row_reference_new (tree_model, path); + + if (!_gtk_tree_view_find_node (GTK_TREE_VIEW (gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible))), + path, + &cell_info->tree, + &cell_info->node)) + { + /* This check needs to happen way earlier */ + g_free (cell_info); + return; + } cell_info->cell_col_ref = tv_col; cell_info->cell = cell; @@ -3504,3 +3514,63 @@ get_header_from_column (GtkTreeViewColumn *tv_col) return rc; } + +/** + * _gtk_rbtree_get_ancestor_node: + * @ancestor: the ancestor tree + * @child_tree: the potential child's tree + * @child_node: the potential child's node + * + * Finds the node that is the ancestor of @child_tree and @child_node + * and belongs to @ancestor. If @ancestor is not an ancestor tree + * of @child_node, %NULL is returned. + * + * Returns: the ancestor node or %NULL if @ancestor is not an ancestor. + **/ +static GtkRBNode * +_gtk_rbtree_get_ancestor_node (GtkRBTree *ancestor, + GtkRBTree *child_tree, + GtkRBNode *child_node) +{ + while (child_tree != NULL) + { + if (child_tree == ancestor) + return child_node; + + child_node = child_tree->parent_node; + child_tree = child_tree->parent_tree; + } + + return NULL; +} + +void +_gtk_tree_view_accessible_remove (GtkTreeView *treeview, + GtkRBTree *tree, + GtkRBNode *node) +{ + GtkTreeViewAccessibleCellInfo *cell_info; + GHashTableIter iter; + GtkTreeViewAccessible *accessible; + + accessible = GTK_TREE_VIEW_ACCESSIBLE (_gtk_widget_peek_accessible (GTK_WIDGET (treeview))); + if (accessible == NULL) + return; + + /* if this shows up in profiles, special-case node->children == NULL */ + + g_hash_table_iter_init (&iter, accessible->cell_infos); + while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&cell_info)) + { + GtkRBNode *child_node = _gtk_rbtree_get_ancestor_node (tree, + cell_info->tree, + cell_info->node); + + if (child_node == NULL) + continue; + + if (node == NULL || node == child_node) + g_hash_table_iter_remove (&iter); + } +} + diff --git a/gtk/a11y/gtktreeviewaccessible.h b/gtk/a11y/gtktreeviewaccessible.h index c04a81615b..e7de687cbf 100644 --- a/gtk/a11y/gtktreeviewaccessible.h +++ b/gtk/a11y/gtktreeviewaccessible.h @@ -21,6 +21,7 @@ #define __GTK_TREE_VIEW_ACCESSIBLE_H__ #include "gtkcontaineraccessible.h" +#include "gtktreeprivate.h" G_BEGIN_DECLS @@ -58,6 +59,11 @@ struct _GtkTreeViewAccessibleClass GType _gtk_tree_view_accessible_get_type (void); +/* called by treeview code */ +void _gtk_tree_view_accessible_remove (GtkTreeView *treeview, + GtkRBTree *tree, + GtkRBNode *node); + G_END_DECLS #endif /* __GTK_TREE_VIEW_ACCESSIBLE_H__ */ diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c index 62aec17201..2da21a655e 100644 --- a/gtk/gtktreeview.c +++ b/gtk/gtktreeview.c @@ -9043,10 +9043,12 @@ gtk_tree_view_row_deleted (GtkTreeModel *model, if (tree_view->priv->tree == tree) tree_view->priv->tree = NULL; + _gtk_tree_view_accessible_remove (tree_view, tree, NULL); _gtk_rbtree_remove (tree); } else { + _gtk_tree_view_accessible_remove (tree_view, tree, node); _gtk_rbtree_remove_node (tree, node); } @@ -12900,6 +12902,8 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view, tree_view->priv->last_button_x = -1; tree_view->priv->last_button_y = -1; + _gtk_tree_view_accessible_remove (tree_view, node->children, NULL); + if (gtk_tree_view_unref_and_check_selection_tree (tree_view, node->children)) { _gtk_rbtree_remove (node->children); -- 2.30.2